package com.globefrog.framework.log;

import com.globefrog.framework.common.constant.LogConstants;
import com.globefrog.framework.common.enums.ActionResultEnum;
import com.globefrog.framework.common.enums.LogLevelEnum;
import com.globefrog.framework.log.util.StringExtUtil;
import java.util.UUID;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

/**
 * 日志帮助类.
 *
 * @author caijinbang
 * @date 2020-11-08 16:26
 */
public class LogHelper {

  public LogHelper() {

  }

  public void initLog(LogLevelEnum logLevel, String requestId, String ip, String method,
      String action) {
    initLog(logLevel, requestId, ip, method, action, "");
  }

  /**
   * 初始化.
   *
   * @param logLevel   日志等级
   * @param requestId  请求id
   * @param ip         ip
   * @param method     请求方法
   * @param action     请求动作
   * @param requestUri 请求uri
   */
  private void initLog(LogLevelEnum logLevel, String requestId, String ip, String method,
      String action, String requestUri) {
    String uuid = UUID.randomUUID().toString();
    String actualRequestId = StringUtils.isEmpty(requestId) ? uuid : requestId;
    switch (logLevel) {
      case ACTION:
        initActionLog(actualRequestId, ip, method, action, requestUri);
        break;
      case TRACE:
        initTraceLog(actualRequestId, action);
        MDC.put(LogConstants.MDC_ORIGIN_THREAD_ID, String.valueOf(Thread.currentThread().getId()));
        break;
      case ALL:
        initActionLog(actualRequestId, ip, method, action, requestUri);
        initTraceLog(actualRequestId, action);
        MDC.put(LogConstants.MDC_ORIGIN_THREAD_ID, String.valueOf(Thread.currentThread().getId()));
        break;
      case NONE:
      default:
    }
  }

  /**
   * 初始化子日志.
   *
   * @param logLevel 日志级别
   * @param method   请求方式
   */
  public void initSubLog(LogLevelEnum logLevel, String method) {
    String requestId = MDC.get(LogConstants.MDC_REQUEST_ID);
    String action = MDC.get(LogConstants.MDC_ACTION);
    requestId = StringExtUtil.isNotEmpty(requestId) ? requestId : UUID.randomUUID().toString();
    switch (logLevel) {
      case TRACE:
        this.initTraceLog(requestId, action);
        break;
      case ACTION:
        this.initActionLog(requestId, "", method, action);
        break;
      case ALL:
        this.initActionLog(requestId, "", method, action);
        this.initTraceLog(requestId, action);
        break;
      case NONE:
      default:
    }
  }

  /**
   * 初始化无uri的actioLog.
   *
   * @param requestId 请求id
   * @param ip        ip
   * @param method    请求方式
   * @param action    动作
   */
  public void initActionLog(String requestId, String ip, String method, String action) {
    this.initActionLog(requestId, ip, method, action, "");
  }

  /**
   * 初始化 actionLog.
   *
   * @param requestId 请求id
   * @param ip        ip
   * @param method    请求方式
   * @param action    动作
   * @param uri       uri
   */
  public void initActionLog(String requestId, String ip, String method, String action, String uri) {
    ActionLogImpl actionLogger = ActionLogImpl.getInstance();
    actionLogger.initialize();
    ActionLog actionLog = actionLogger.currentActionLog();
    actionLog.setRequestId(requestId);
    actionLog.setClientIp(ip);
    actionLog.setHttpMethod(method);
    actionLog.setAction(action);
    actionLog.setRequestUri(uri);
  }

  /**
   * 初始化TraceLog.
   *
   * @param requestId 请求id
   * @param action    动作
   */
  public void initTraceLog(String requestId, String action) {
    TraceLogger traceLogger = TraceLogger.getInstance();
    traceLogger.initialize();
    MDC.put(LogConstants.MDC_REQUEST_ID, requestId);
    MDC.put(LogConstants.MDC_ACTION, action);
  }

  /**
   * 结束日志.
   *
   * @param logLevel 日志级别
   */
  public void endLog(LogLevelEnum logLevel) {
    switch (logLevel) {
      case ACTION:
        ActionLogImpl.getInstance().save();
        break;
      case TRACE:
        TraceLogger.getInstance().cleanup(Boolean.FALSE);
        break;
      case ALL:
        ActionLogImpl.getInstance().save();
        TraceLogger.getInstance().cleanup(Boolean.FALSE);
        break;
      case NONE:
      default:
    }
  }

  /**
   * 将ERROR级别的日志打到actionLog.
   *
   * @param e 异常
   */
  public void actionLogError(Throwable e) {
    ActionLog actionLog = ActionLogImpl.getInstance().currentActionLog();
    if (actionLog != null) {
      actionLog.setResult(ActionResultEnum.ERROR);
      actionLog.setException(e.getClass().getName());
      actionLog.setErrorMessage(e.getMessage());
    }

  }

  /**
   * 将WARN级别的日志异常信息打到actionLog.
   *
   * @param e 异常
   */
  public void actionLogWarning(Throwable e) {
    ActionLog actionLog = ActionLogImpl.getInstance().currentActionLog();
    if (actionLog != null) {
      actionLog.setResult(ActionResultEnum.WARNING);
      actionLog.setException(e.getClass().getName());
      actionLog.setErrorMessage(e.getMessage());
    }
  }

  public void withStatusCode(Integer statusCode) {
    ActionLog actionLog = ActionLogImpl.getInstance().currentActionLog();
    if (actionLog != null) {
      actionLog.setHttpStatusCode(statusCode);
    }
  }
}
